import axios from 'axios'
import qs from 'qs'
import {
  MockPost
} from './mock.js'

import {
  API_URL,
} from '@utils/default_config'
import {
  IS_PC_APP, // 是否为 pc 项目
} from '@utils/utils'
import {
  getSignInByKey,
  setSignOut,
} from '@utils/storage_base_config'
import {
  goPage,
  LOGIN_PATH_NAME,
  HOME_PATH_NAME,
} from '@router/path'
import {
  getRole
} from '@utils/role'

import Toast from '@utils/toast'

axios.defaults.baseURL = API_URL
axios.defaults.withCredentials = true
axios.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded'
axios.defaults.headers.common["Accept"] = 'application/json, text/javascript, */*; q=0.01'
axios.defaults.headers.common["request-from"] = IS_PC_APP ? 'pc' : 'm'

// 请求拦截器
axios.interceptors.request.use(config => {
  config.timeout = 10000
  config.future = true
  config.headers.common["Authorization"] = `Bearer ${getSignInByKey('access_token')}`
  return config
}, error => {
  return Promise.error(error)
})

// 响应拦截器
axios.interceptors.response.use(responseConfig => {
  const {
    status,
    data: resData,
    headers,
    config,
  } = responseConfig

  if (status !== 200)
    return Promise.reject(responseConfig)

  if (resData.code === 402 || resData.code === 401) { // token过期或者未登录
    debugger
    setSignOut()
    goPage(LOGIN_PATH_NAME, {
      role: getRole(),
    })
    return Promise.reject(responseConfig)
  }
  if (resData.code === 405) { // 没有分销商权限（eg. 某个产品不属于当前的分销商）
    debugger
    goPage(HOME_PATH_NAME, {}, true)
    return Promise.reject(responseConfig)
  }

  const isFile = config.responseType === 'blob'

  if (!resData || (!isFile && (resData.code !== 200 || !resData.data))) {
    if (!(
        resData.code === 412 // 微信登录时未绑定微信账号。这种情况不属于错误。
      )) {
      rejectToast(responseConfig, config.url)
    }
    return Promise.reject(responseConfig)
  } else {
    if (isFile) {
      const hasFileName = headers['content-disposition'] && headers['content-disposition'].match(/^filename="([^"]+)"$/)
      return Promise.resolve({
        data: resData,
        fileName: (hasFileName && hasFileName[1]) ? decodeURIComponent(escape(hasFileName[1])) : ''
      })
    }
    return Promise.resolve(resData)
  }
}, error => {
  rejectToast(error)
  return Promise.reject(error)
})

// 统一处理弹出提示
let dontShowErrMap = {} // 记录不需要弹出提示的请求
function rejectToast(error, url) {
  if (url && dontShowErrMap[url])
    return
  const {
    status,
    msg
  } = getErrInfo(error)
  status ? console.warn(status, msg) : console.warn(error)
  Toast(msg || '请求错误！')
}

/**
 * 过滤错误信息
 * @param {*} error 
 */
export function getErrInfo(error) {
  let status = '',
    msg = '';
  if (error.response) {
    if (error.response.status) {
      status = error.response.data.code
      msg = error.response.data.msg || error.response.data.message
    }
    if (!status)
      status = error.response.status
    if (!msg)
      msg = error.response.statusText
  } else if (error.data) {
    status = error.data.code
    msg = error.data.msg
  }
  return {
    status,
    msg
  }
}

// get 请求
export function get({
  url,
  data = {},
  headers = {},
  isAlertErr,
}) {
  if (isAlertErr === false) {
    dontShowErrMap[url] = true
  }
  if (data.mock) { // 需要mock的请求
    return MockPost(url, data);
  } else {
    delete data.mock
    return new Promise((resolve, reject) => {
      addHeader(headers)
      axios.get(url, {
        params: data
      }).then(res => {
        resolve(res)
      }).catch(err => {
        reject(err)
      }).finally(() => {
        delete dontShowErrMap[url]
      })
    })
  }
}
// TODO: mock 参数不要带在data中
// TODO: 为什么post要写一层request请求？？？
// post请求
function request({
  url,
  data = {},
  params = {},
  isAlertErr,
}) {
  if (isAlertErr === false) {
    dontShowErrMap[axios.defaults.baseURL + url] = true
  }
  return new Promise((resolve, reject) => {
    data = qs.stringify({
      ...data
    })
    axios.post(url, data).then(res => {
      resolve(res)
    }).catch(err => {
      reject(err);
    }).finally(() => {
      delete dontShowErrMap[url]
    })
  })
}

/* 个别请求新增请求头部 */
function addHeader(headers = {}) {
  if (Object.keys(headers).length) {
    for (let i in headers) {
      axios.defaults.headers.common[i] = headers[i]
    }
  }
}

export function post({
  url,
  data = {},
  params = {},
  headers = {},
  isAlertErr,
}) {
  if (data.mock) { // 需要mock的请求
    return MockPost(url, data);
  } else {
    delete data.mock
    addHeader(headers)
    return request({
      url,
      data,
      params,
      isAlertErr,
    })
  }
}

// 请求文件
export function getFile({
  url,
  data = {},
  headers = {}
}) {
  return new Promise((resolve, reject) => {
    addHeader(headers)
    axios.get(url, {
      params: data,
      responseType: 'blob',
    }).then(res => {
      const url = window.URL.createObjectURL(new Blob([res.data]));
      const downloadEl = document.createElement('a');
      downloadEl.href = url;
      downloadEl.setAttribute('download', res.fileName);
      document.body.appendChild(downloadEl);
      downloadEl.click();
      document.body.removeChild(downloadEl);
      window.URL.revokeObjectURL(url);
      resolve(res)
    }).catch(res => {
      reject(res)
    })
  })
}